﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// EasyPool 的回收接口,继承可使用BhvEasyPool回收对象
/// </summary>
public interface IPoolRecycle
{
    /// <summary>
    /// 从对象池取出时触发该方法
    /// </summary>
    void OnRecycleGet();

    /// <summary>
    /// 放入对象池触发该方法
    /// </summary>
    void OnRecyclePut();

}
public class GameobjectPool
{
    private GameObject cloneObject;
    public Stack<GameObject> stack = new Stack<GameObject>();
    private int cacheCount = 3;
    private int maxPoolCount = -1;

    private Transform parent;
    /// <summary>
    /// 对象池
    /// </summary>
    /// <param name="prefab">对象池模板</param>
    /// <param name="parent">对象池根节点(默认为场景根节点)</param>
    /// <param name="cacheCount">对象池缓存数量(初始缓存)</param>
    /// <param name="maxPoolCount">对象池缓存的最大数量限制，如果超过就返回null</param>
    public GameobjectPool(GameObject prefab, Transform parent = null, int cacheCount = 3, int maxPoolCount = -1)
    {

        this.stack.Clear();
        this.cloneObject = prefab;
        this.parent = parent;
        this.cacheCount = cacheCount;
        this.maxPoolCount = maxPoolCount;

        if (this.cloneObject == null && parent != null)
        {
            this.cloneObject = parent.GetChild(0).gameObject;
            this.cloneObject.SetActive(false);
        }

        //加入缓存
        for (int i = 0; i < cacheCount; i++)
        {
            var obj = GameObject.Instantiate(this.cloneObject);
            obj.transform.SetParent(parent);
            Put(obj);
        }


    }

    public GameObject Get()
    {
        GameObject obj;

        if (this.cloneObject == null)
        {
            Debug.LogWarning("CloneObject Is Null!");
            return null;
        }

        if (stack.Count <= 0)
        {
            obj = GameObject.Instantiate(cloneObject);
        }
        else
        {
            obj = stack.Pop() as GameObject;
        }

        obj.SetActive(true);
        obj.transform.SetParent(this.parent);
        //重设默认值
        obj.transform.localScale = cloneObject.transform.localScale;
        obj.transform.rotation = cloneObject.transform.rotation;
        obj.transform.position = cloneObject.transform.position;

        obj.GetComponent<IPoolRecycle>()?.OnRecycleGet();

        return obj;
    }

    //放入对象池中的对象
    public void Put(GameObject obj)
    {
        obj.GetComponent<IPoolRecycle>()?.OnRecyclePut();
        obj.SetActive(false);

        if (obj.transform != parent)
        {
            obj.transform.SetParent(parent);//回收设置为此对象内部
        }

        if (stack.Contains(obj) == false)
        {
            stack.Push(obj);
        }

        cacheCount = parent.childCount;
    }

    /// <summary>
    /// 回收所有可见对象
    /// </summary>
    public void PutAll()
    {
        if (parent == null) return;
        for (int i = 0; i < parent.childCount; i++)
        {
            var obj = parent.GetChild(i).gameObject;
            if (obj.activeSelf) Put(obj);
        }
    }

    /// <summary>
    /// 清理对象池对象，并且清除所有缓存
    /// </summary>
    /// <param name="destroyAll"></param>
    public void Clear(bool destroyAll = true)
    {
        if (destroyAll)
        {
            foreach (var item in stack)
            {
                GameObject.Destroy(item.gameObject);
            }
        }

        stack.Clear();
    }

}

